import fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';
import express from 'express';
import cron from 'node-cron';

// 配置部分
const config = {
    projectPath: 'C:\\Users\\li\\Desktop\\项目\\zaixianjiaoyi\\admin',
    giteeRepo: 'https://gitee.com/liyucheng369/Rouyi.git',
    branch: 'main',
    logFile: './modification_log.json',
    port: 3000,
    cronSchedule: '* * * * *',
    gitUserName: 'liyucheng369',
    gitUserEmail: '823976085@qq.com'
};

// 修改方法集合
const modificationMethods = [
    (functionCode, functionName) => {
        const newParam = `newParam${Math.floor(Math.random() * 100)}`;
        return functionCode.replace(/(function\s+\w+\s*\([^)]*)/, `$1, ${newParam}`);
    },
    (functionCode, functionName) => {
        const vars = functionCode.match(/(let|const|var)\s+(\w+)/g) || [];
        if (vars.length > 0) {
            const randomVar = vars[Math.floor(Math.random() * vars.length)];
            const oldName = randomVar.split(/\s+/)[1];
            const newName = `renamed${Math.floor(Math.random() * 100)}`;
            return functionCode.replace(new RegExp(`\\b${oldName}\\b`, 'g'), newName);
        }
        return functionCode;
    },
    (functionCode, functionName) => {
        const lines = functionCode.split('\n');
        const insertIndex = Math.max(1, Math.floor(Math.random() * lines.length));
        lines.splice(insertIndex, 0, `    console.log("${functionName} executed");`);
        return lines.join('\n');
    }
];

// 日志系统
class Logger {
    constructor(logFile) {
        this.logFile = logFile;
        this.ensureLogFile();
    }

    ensureLogFile() {
        if (!fs.existsSync(this.logFile)) {
            fs.writeFileSync(this.logFile, JSON.stringify([], null, 2));
        }
    }

    log(operation, file, functionName, success = true, message = '') {
        const entry = {
            timestamp: new Date().toISOString(),
            operation,
            file,
            functionName,
            success,
            message
        };

        const logs = JSON.parse(fs.readFileSync(this.logFile, 'utf8'));
        logs.push(entry);
        fs.writeFileSync(this.logFile, JSON.stringify(logs, null, 2));
        console.log(`[${entry.timestamp}] ${operation} ${success ? '成功' : '失败'}: ${file} -> ${functionName} ${message}`);
    }

    getLogs(limit = 50) {
        const logs = JSON.parse(fs.readFileSync(this.logFile, 'utf8'));
        return logs.slice(-limit);
    }
}

// 主功能类
class CodeModifier {
    constructor(config) {
        this.config = config;
        this.logger = new Logger(config.logFile);
        this.lastRun = null;
        this.nextRun = null;
        this.isRunning = false;
        this.gitInitialized = false;

        // 函数名前缀数组（英文）
        this.functionPrefixes = [
            'decompressor', 'compressor', 'encoder', 'decoder', 'encryptor', 'decryptor',
            'validator', 'sanitizer', 'formatter', 'parser', 'converter', 'transformer',
            'calculator', 'analyzer', 'detector', 'finder', 'searcher', 'matcher',
            'sorter', 'filter', 'aggregator', 'collector', 'accumulator', 'reducer',
            'composer', 'combiner', 'merger', 'splitter', 'divider', 'separator',
            'extractor', 'injector', 'initializer', 'terminator', 'destroyer', 'cleaner',
            'saver', 'loader', 'fetcher', 'sender', 'receiver', 'transmitter',
            'communicator', 'connector', 'linker', 'binder', 'wrapper', 'adapter',
            'decorator', 'enhancer', 'amplifier', 'booster', 'accelerator', 'optimizer',
            'enhanced', 'modified', 'updated', 'advanced', 'optimized', 'improved',
            'extended', 'custom', 'dynamic', 'smart', 'intelligent', 'fast',
            'secure', 'reliable', 'stable', 'robust', 'flexible', 'scalable',
            'efficient', 'powerful', 'modern', 'nextGen', 'pro', 'enterprise',
            'cloud', 'web', 'mobile', 'desktop', 'api', 'microservice'
        ];

        // 函数名后缀数组（英文）
        this.functionSuffixes = [
            'Handler', 'Function', 'Util', 'Helper', 'Assistant', 'Tool',
            'Module', 'Component', 'Plugin', 'Extension', 'Addon', 'Library',
            'Package', 'Bundle', 'Kit', 'Suite', 'Collection', 'Set',
            'Array', 'List', 'Stack', 'Queue', 'Tree', 'Graph',
            'Map', 'Dictionary', 'Table', 'Matrix', 'Vector', 'Scalar',
            'Object', 'Entity', 'Model', 'Record', 'Document', 'File',
            'Stream', 'Buffer', 'Cache', 'Memory', 'Storage', 'Database',
            'Repository', 'Archive', 'Backup', 'Snapshot', 'Image', 'View',
            'Template', 'Layout', 'Frame', 'Panel', 'Window', 'Dialog',
            'Form', 'Sheet', 'Page', 'Screen', 'Display', 'Monitor',
            'Controller', 'Director', 'Coordinator', 'Organizer', 'Arranger', 'Planner',
            'Scheduler', 'Timer', 'Clock', 'Calendar', 'Date', 'Time',
            'Number', 'String', 'Text', 'Character', 'Byte', 'Bit',
            'Boolean', 'Flag', 'Switch', 'Toggle', 'Button', 'Key',
            'Lock', 'Security', 'Auth', 'Login', 'Session', 'Token'
        ];

        // 中文提交信息选项
        this.commitTypes = ['运维', '开发', '修改', '功能', '优化', '更新', '修复', '测试', '调整', '重构'];
        this.commitActions = ['开发了', '添加了', '实现了', '创建了', '扩展了', '改进了', '优化了', '完成了', '调整了', '重构了'];
    }

    // 执行 Git 命令
    execGitCommand(command, options = {}) {
        try {
            return execSync(command, {
                cwd: this.config.projectPath,
                stdio: 'pipe',
                ...options
            }).toString().trim();
        } catch (error) {
            throw new Error(`Git命令失败: ${command}\n${error.stderr?.toString() || error.message}`);
        }
    }

    // 初始化 Git 仓库
    async initializeGitRepository() {
        if (this.gitInitialized) return true;

        try {
            // 设置全局 Git 配置
            this.execGitCommand(`git config --global user.name "${this.config.gitUserName}"`);
            this.execGitCommand(`git config --global user.email "${this.config.gitUserEmail}"`);

            // 设置本地 Git 配置
            this.execGitCommand(`git config user.name "${this.config.gitUserName}"`);
            this.execGitCommand(`git config user.email "${this.config.gitUserEmail}"`);

            // 检查是否是 Git 仓库
            try {
                this.execGitCommand('git status');
                console.log('Git仓库已存在');
            } catch {
                console.log('初始化新的Git仓库...');
                this.execGitCommand('git init');
                this.execGitCommand(`git remote add origin ${this.config.giteeRepo}`);
            }

            // 检查分支
            const branches = this.execGitCommand('git branch');
            if (!branches.includes(this.config.branch)) {
                this.execGitCommand(`git checkout -b ${this.config.branch}`);
            } else {
                this.execGitCommand(`git checkout ${this.config.branch}`);
            }

            // 创建初始提交
            try {
                this.execGitCommand('git add .');
                this.execGitCommand('git commit -m "初始提交: 由自动修改器创建"');
            } catch {
                // 如果已经有提交，忽略错误
            }

            this.gitInitialized = true;
            console.log('Git仓库初始化成功');
            return true;

        } catch (error) {
            console.error('Git初始化失败:', error.message);
            return false;
        }
    }

    // 查找所有代码文件
    findAllCodeFiles(dirPath, arrayOfFiles = []) {
        try {
            const files = fs.readdirSync(dirPath);
            files.forEach(file => {
                const fullPath = path.join(dirPath, file);
                try {
                    if (fs.statSync(fullPath).isDirectory()) {
                        if (!file.includes('node_modules') && !file.includes('.git')) {
                            this.findAllCodeFiles(fullPath, arrayOfFiles);
                        }
                    } else if (file.match(/\.(js|ts|vue)$/)) {
                        arrayOfFiles.push(fullPath);
                    }
                } catch (error) {
                    console.log(`跳过 ${fullPath}: ${error.message}`);
                }
            });
        } catch (error) {
            console.log(`读取目录错误 ${dirPath}: ${error.message}`);
        }
        return arrayOfFiles;
    }

    // 从文件中提取函数
    extractFunctions(code, fileExt) {
        const functions = [];
        if (!code) return functions;

        try {
            const reservedKeywords = new Set(['if', 'for', 'while', 'switch', 'try', 'catch']);

            const functionRegex = /(function\s+(\w+)|(const|let|var)\s+(\w+)\s*=\s*(async\s*)?\s*function|(const|let|var)\s+(\w+)\s*=\s*\([^)]*\)\s*=>|(\w+)\s*\([^)]*\)\s*{)/g;
            let match;

            while ((match = functionRegex.exec(code)) !== null) {
                let functionName = match[2] || match[4] || match[7] || match[8];
                if (!functionName || reservedKeywords.has(functionName)) continue;

                const startPos = match.index;
                let braceCount = 0;
                let endPos = startPos;
                let foundStart = false;

                for (let i = startPos; i < Math.min(startPos + 1000, code.length); i++) {
                    if (code[i] === '{') {
                        braceCount++;
                        foundStart = true;
                    }
                    if (code[i] === '}') braceCount--;
                    if (foundStart && braceCount === 0) {
                        endPos = i;
                        break;
                    }
                }

                if (endPos > startPos) {
                    functions.push({
                        name: functionName,
                        code: code.substring(startPos, endPos + 1),
                        start: startPos,
                        end: endPos + 1
                    });
                }
            }
        } catch (error) {
            console.log('提取函数错误:', error.message);
        }
        return functions;
    }

    // 生成随机函数名（英文驼峰命名）
    generateRandomFunctionName(originalName) {
        const prefix = this.functionPrefixes[Math.floor(Math.random() * this.functionPrefixes.length)];
        const suffix = this.functionSuffixes[Math.floor(Math.random() * this.functionSuffixes.length)];
        // 将原函数名首字母大写，保持驼峰命名
        const capitalizedOriginal = originalName.charAt(0).toUpperCase() + originalName.slice(1);
        return prefix + capitalizedOriginal + suffix;
    }

    // 生成中文提交信息
    generateChineseCommitMessage(functionName) {
        const randomType = this.commitTypes[Math.floor(Math.random() * this.commitTypes.length)];
        const randomAction = this.commitActions[Math.floor(Math.random() * this.commitActions.length)];
        return `${randomType}: ${randomAction} ${functionName}()方法`;
    }

    // 执行修改
    async modifyAndCommit() {
        if (this.isRunning) return;
        this.isRunning = true;
        this.lastRun = new Date();

        try {
            console.log('开始修改过程...');

            // 初始化 Git
            if (!await this.initializeGitRepository()) {
                throw new Error('Git初始化失败');
            }

            // 查找代码文件
            const codeFiles = this.findAllCodeFiles(this.config.projectPath);
            if (codeFiles.length === 0) throw new Error('未找到代码文件');

            // 选择文件和函数
            let functions = [];
            let randomFile = '';
            for (let i = 0; i < 3 && functions.length === 0; i++) {
                randomFile = codeFiles[Math.floor(Math.random() * codeFiles.length)];
                const fileContent = fs.readFileSync(randomFile, 'utf8');
                functions = this.extractFunctions(fileContent, path.extname(randomFile));
            }
            if (functions.length === 0) throw new Error('未找到函数');

            const randomFunction = functions[Math.floor(Math.random() * functions.length)];
            const newFunctionName = this.generateRandomFunctionName(randomFunction.name);

            // 修改并写入文件
            const fileContent = fs.readFileSync(randomFile, 'utf8');
            const newFileContent = fileContent + `\n\n// Auto-generated function\n${randomFunction.code.replace(new RegExp(`\\b${randomFunction.name}\\b`, 'g'), newFunctionName)}`;
            fs.writeFileSync(randomFile, newFileContent);

            // 生成中文提交信息
            const commitMessage = this.generateChineseCommitMessage(newFunctionName);

            // Git 操作
            this.execGitCommand('git add .');
            this.execGitCommand(`git commit -m "${commitMessage}"`);

            // 推送到远程
            try {
                this.execGitCommand(`git push -u origin ${this.config.branch}`);
            } catch {
                this.execGitCommand(`git push -f origin ${this.config.branch}`);
            }

            this.logger.log('修改', path.basename(randomFile), randomFunction.name, true, `添加了 ${newFunctionName}`);
            console.log('修改完成! 提交信息:', commitMessage);

        } catch (error) {
            this.logger.log('执行', '系统', 'N/A', false, error.message);
            console.error('错误:', error.message);
        } finally {
            this.isRunning = false;
        }
    }

    // 启动定时任务
    startScheduler() {
        console.log('启动调度器...');
        cron.schedule(this.config.cronSchedule, () => this.modifyAndCommit());
        this.startMonitorServer();
        setTimeout(() => this.modifyAndCommit(), 2000);
    }

    // 启动监控服务器
    startMonitorServer() {
        const app = express();
        app.get('/', (req, res) => {
            res.send(`
            <html><body>
                <h1>代码修改器监控</h1>
                <p>状态: ${this.isRunning ? '运行中' : '空闲'}</p>
                <p>上次运行: ${this.lastRun ? this.lastRun.toLocaleString() : '从未运行'}</p>
                <p>函数前缀: ${this.functionPrefixes.length} 个可用</p>
                <p>函数后缀: ${this.functionSuffixes.length} 个可用</p>
                <p>总组合数: ${this.functionPrefixes.length * this.functionSuffixes.length} 种可能的函数名</p>
            </body></html>
            `);
        });
        app.listen(this.config.port, () => {
            console.log(`监控服务器运行在 http://localhost:${this.config.port}`);
        });
    }
}

// 主程序
const modifier = new CodeModifier(config);
modifier.startScheduler();